<!DOCTYPE html><html><head hexo-theme="https://github.com/volantis-x/hexo-theme-volantis/tree/3.0.0"><meta charset="utf-8"><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><meta name="HandheldFriendly" content="True"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><title>工作中常用到的ES6语法 - 忆星辰</title><meta name="keywords" content="JavaScript"><meta name="description" content="在JavaScript中咱们以前主要用关键var来定义变量，ES6之后，新增了定义变量的两个关键字，分别是let和const。对于变量来说，在ES5中var定义的变量会提升到作用域中所有的函数与语句前面，而ES6中let定义的变量则不会，let声明的变量会在其相应的代码块中建立一个暂时性死区，直至变量被声明。let和const都能够声明块级作用域，用法和var是类似的，let的特点是不会变量提升，而是被锁在当前块中。"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.css"><link rel="shortcut icon" type="image/x-icon" href="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/avatar/favicon-cicle.png"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.css"><link rel="stylesheet" href="/css/style.css"><script>setTimeout(function(){window.ga_tid="UA-124641144-1",function(){var e=document.createElement("script");e.src="https://rmt.dogedoge.com/fetch/public/ga.js";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()},5e3)</script><script>var _hmt=_hmt||[];setTimeout(function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?e98a157d14b712d66463073d921b0253",e.defer=!0;var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)},5e3)</script></head><body><header class="l_header auto shadow blur" style="opacity:0"><div class="container"><div class="wrapper"><div class="nav-sub"><p class="title"></p><ul class="switcher nav-list-h m-phone" id="pjax-header-nav-list"><li><a class="s-comment fas fa-comments fa-fw" target="_self" href="javascript:void(0)"></a></li><li><a class="s-toc fas fa-list fa-fw" target="_self" href="javascript:void(0)"></a></li></ul></div><div class="nav-main"><a class="title flat-box" target="_self" href="/"><img no-lazy class="logo" src="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/avatar/favicon-cicle.png"> <i class="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/avatar/favicon-cicle.png"></i></a><div class="menu navigation"><ul class="nav-list-h m-pc"><li><a class="menuitem flat-box faa-parent animated-hover" href="/" id="home"><i class="fas fa-rss fa-fw"></i>博客</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i>归档</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i>标签</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" id="categories"><i class="fas fa-folder-open fa-fw"></i>分类</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/friends/" id="friends"><i class="fas fa-link fa-fw"></i>友链</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/shuoshuo/" id="shuoshuo"><i class="fas fa-comments fa-fw"></i>说说</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/about/" id="about"><i class="fas fa-info-circle fa-fw"></i>关于</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tools/" id="tools"><i class="fas fa-tools fa-fw"></i>工具箱</a></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-ellipsis-v fa-fw"></i>更多</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/comments/" id="comments"><i class="fas fa-file-signature fa-fw"></i>留言板</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/bangumis/index.html" id="bangumisindexhtml"><i class="fas fa-tv fa-fw"></i>番剧</a></li></ul></li></ul></div><div class="m_search"><form name="searchform" class="form u-search-form"><i class="icon fas fa-search fa-fw"></i> <input type="text" class="input u-search-input" placeholder="Search..."></form></div><ul class="switcher nav-list-h m-phone"><li><a class="s-search fas fa-search fa-fw" target="_self" href="javascript:void(0)"></a></li><li><a class="s-menu fas fa-bars fa-fw" target="_self" href="javascript:void(0)"></a><ul class="menu-phone list-v navigation white-box"><li><a class="menuitem flat-box faa-parent animated-hover" href="/" id="home"><i class="fas fa-rss fa-fw"></i>博客</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i>归档</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i>标签</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" id="categories"><i class="fas fa-folder-open fa-fw"></i>分类</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/friends/" id="friends"><i class="fas fa-link fa-fw"></i>友链</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/shuoshuo/" id="shuoshuo"><i class="fas fa-comments fa-fw"></i>说说</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/about/" id="about"><i class="fas fa-info-circle fa-fw"></i>关于</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tools/" id="tools"><i class="fas fa-tools fa-fw"></i>工具箱</a></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-ellipsis-v fa-fw"></i>更多</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/comments/" id="comments"><i class="fas fa-file-signature fa-fw"></i>留言板</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/bangumis/index.html" id="bangumisindexhtml"><i class="fas fa-tv fa-fw"></i>番剧</a></li></ul></li></ul></li></ul></div></div></div></header><div class="l_body"><div class="l_cover"><div class="cover-wrapper post dock" style="display:none"><div class="cover-backstretch"></div><div class="cover-body"><div class="top"><img no-lazy class="logo" src="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/avatar/favicon-cicle.png"></div><div class="bottom"><div class="menu navigation"><div class="list-h"><a href="/" id="home"><i class="fas fa-book fa-fw"></i><p>博客</p></a><a href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i><p>归档</p></a><a href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i><p>标签</p></a><a href="/friends/" id="friends"><i class="fas fa-link fa-fw"></i><p>友链</p></a><a href="/shuoshuo/" id="shuoshuo"><i class="fas fa-comments fa-fw"></i><p>说说</p></a><a href="/about/" id="about"><i class="fas fa-info-circle fa-fw"></i><p>关于</p></a></div></div></div></div><div class="scroll-down" style="display:none"><i class="fa fa-chevron-down scroll-down-effects"></i></div></div></div><div class="safearea"><div class="body-wrapper" id="pjax-container"><div id="pjax-data" style="display:none"><div id="pjax-ispage">true</div><div id="pjax-pageTitle">工作中常用到的ES6语法</div><div id="pjax-enable-cover">true</div><div id="pjax-comment-path">none</div><div id="pjax-comment-placeholder">none</div></div><script>document.getElementsByClassName("cover-wrapper")[0].style.display="none",document.getElementsByClassName("l_header","cover-wrapper")[0].classList.add("show")</script><div class="l_main"><article id="post" class="post white-box reveal md shadow article-type-post" itemscope itemprop="blogPost"><div class="article-header"><div class="article-meta" id="top"><h1 class="title"><a href="/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/">工作中常用到的ES6语法</a></h1><div class="new-meta-box"><div class="new-meta-item author"><a class="author" href="/" rel="nofollow"><img no-lazy src="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/avatar/avatar.jpg"><p>Akimoto</p></a></div><div class="new-meta-item category"><a class="notlink"><i class="fas fa-folder-open fa-fw" aria-hidden="true"></i> <a class="category-link" href="/categories/JavaScript/">JavaScript</a></a></div><div class="new-meta-item date"><a class="notlink"><i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i><p>发布于：2018年9月11日</p></a></div><div class="new-meta-item wordcount"><a class="notlink"><i class="fas fa-keyboard fa-fw" aria-hidden="true"></i><p>字数：4.7k字</p></a></div><div class="new-meta-item readtime"><a class="notlink"><i class="fas fa-hourglass-half fa-fw" aria-hidden="true"></i><p>时长：20分钟</p></a></div><div class="new-meta-item browse leancloud"><a class="notlink"><div id="lc-pv" data-title="工作中常用到的ES6语法" data-path="/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/"><i class="fas fa-eye fa-fw" aria-hidden="true"></i> <span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次阅读</div></a></div></div></div></div><section class="article typo"><div class="article-entry" itemprop="articleBody"><h1 id="一、let和const"><a href="#一、let和const" class="headerlink" title="一、let和const"></a>一、let和const</h1><p>在JavaScript中咱们以前主要用关键var来定义变量，ES6之后，新增了定义变量的两个关键字，分别是let和const。<br>对于变量来说，在ES5中var定义的变量会提升到作用域中所有的函数与语句前面，而ES6中let定义的变量则不会，let声明的变量会在其相应的代码块中建立一个暂时性死区，直至变量被声明。<br><code>let</code>和<code>const</code>都能够声明块级作用域，用法和<code>var</code>是类似的，let的特点是不会变量提升，而是被锁在当前块中。</p><p>一个非常简单的例子：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">function test() &#123;</span><br><span class="line">if(true) &#123;</span><br><span class="line">  console.log(a)&#x2F;&#x2F;TDZ，俗称临时死区，用来描述变量不提升的现象</span><br><span class="line">  let a &#x3D; 1</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">test()  &#x2F;&#x2F; a is not defined</span><br><span class="line"></span><br><span class="line">function test() &#123;</span><br><span class="line">    if(true) &#123;</span><br><span class="line">      let a &#x3D; 1</span><br><span class="line">    &#125;</span><br><span class="line">    console.log(a)</span><br><span class="line">&#125;    </span><br><span class="line">test() &#x2F;&#x2F; a is not defined</span><br></pre></td></tr></table></figure><p>唯一正确的使用方法：先声明，再访问。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">function test() &#123;</span><br><span class="line">    if(true) &#123;</span><br><span class="line">      let a &#x3D; 1</span><br><span class="line">      console.log(a)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">test() &#x2F;&#x2F; 1</span><br></pre></td></tr></table></figure><p><code>const</code><br>声明常量，一旦声明，不可更改，而且常量必须初始化赋值。<br>const虽然是常量，不允许修改默认赋值，但如果定义的是对象Object，那么可以修改对象内部的属性值。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const type &#x3D; &#123;</span><br><span class="line">  a: 1</span><br><span class="line">&#125;</span><br><span class="line">type.a &#x3D; 2 &#x2F;&#x2F;没有直接修改type的值，而是修改type.a的属性值，这是允许的。</span><br><span class="line">console.log(type) &#x2F;&#x2F; &#123;a: 2&#125;</span><br></pre></td></tr></table></figure><h3 id="const和let的异同点"><a href="#const和let的异同点" class="headerlink" title="const和let的异同点"></a>const和let的异同点</h3><p><strong>相同点</strong>：const和let都是在当前块内有效，执行到块外会被销毁，也不存在变量提升（TDZ），不能重复声明。<br><strong>不同点</strong>：const不能再赋值，let声明的变量可以重复赋值。<br>const实际上保证的，并不是变量的值不得改动，而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据（数值、字符串、布尔值），值就保存在变量指向的那个内存地址，因此等同于常量。但对于复合类型的数据（主要是对象和数组），变量指向的内存地址，保存的只是一个指向实际数据的指针，const只能保证这个指针是固定的（即总是指向另一个固定的地址），至于它指向的数据结构是不是可变的，就完全不能控制了。因此，将一个对象声明为常量必须非常小心。</p><h3 id="块级作用域的使用场景"><a href="#块级作用域的使用场景" class="headerlink" title="块级作用域的使用场景"></a>块级作用域的使用场景</h3><p>除了上面提到的常用声明方式，我们还可以在循环中使用，最出名的一道面试题：循环中定时器闭包的考题<br>在for循环中使用var声明的循环变量，会跳出循环体污染当前的函数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">for(var  &#x3D; 0;  &lt; 5; ++) &#123;</span><br><span class="line">  setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log() &#x2F;&#x2F;5, 5, 5, 5, 5</span><br><span class="line">  &#125;, 0)</span><br><span class="line">&#125;</span><br><span class="line">console.log() &#x2F;&#x2F;5 跳出循环体污染外部函数</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;将var改成let之后</span><br><span class="line">for(let  &#x3D; 0;  &lt; 5; ++) &#123;</span><br><span class="line">  setTimeout(() &#x3D;&gt; &#123;</span><br><span class="line">    console.log() &#x2F;&#x2F; 0,1,2,3,4</span><br><span class="line">  &#125;, 0)</span><br><span class="line">&#125;</span><br><span class="line">console.log()&#x2F;&#x2F;i is not defined </span><br></pre></td></tr></table></figure><h3 id="无法污染外部函数"><a href="#无法污染外部函数" class="headerlink" title="无法污染外部函数"></a>无法污染外部函数</h3><p>在实际开发中，我们选择使用var、let还是const，取决于我们的变量是不是需要更新，通常我们希望变量保证不被恶意修改，而使用大量的const。使用const声明，声明一个对象的时候，也推荐使用const，当你需要修改声明的变量值时，使用let，var能用的场景都可以使用let替代。</p><h3 id="symbol"><a href="#symbol" class="headerlink" title="symbol"></a>symbol</h3><p>ES6 以前，我们知道5种基本数据类型分别是<code>Undefined</code>，<code>Null</code>，<code>Boolean</code>，<code>Number</code>以及<code>String</code>，然后加上一种引用类型<code>Object</code>构成了JavaScript中所有的数据类型，但是ES6出来之后，新增了一种数据类型，名叫<code>symbol</code>，像它的名字表露的一样，意味着独一无二，意思是每个 Symbol类型都是独一无二的，不与其它 Symbol 重复。<br>可以通过调用 Symbol() 方法将创建一个新的 Symbol 类型的值，这个值独一无二，不与任何值相等。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">var mySymbol&#x3D;Symbol();</span><br><span class="line">console.log(typeof mySymbol) &#x2F;&#x2F;&quot;symbol&quot;</span><br></pre></td></tr></table></figure><h1 id="二、字符串"><a href="#二、字符串" class="headerlink" title="二、字符串"></a>二、字符串</h1><h3 id="ES6字符串新增的方法"><a href="#ES6字符串新增的方法" class="headerlink" title="ES6字符串新增的方法"></a>ES6字符串新增的方法</h3><p><strong>UTF-16码位</strong>：ES6强制使用UTF-16字符串编码。关于UTF-16的解释请自行百度了解。</p><p>**codePointAt()**：该方法支持UTF-16，接受编码单元的位置而非字符串位置作为参数，返回与字符串中给定位置对应的码位，即一个整数值。</p><p>**String.fromCodePoiont()**：作用与codePointAt相反，检索字符串中某个字符的码位，也可以根据指定的码位生成一个字符。</p><p>**normalize()**：提供Unicode的标准形式，接受一个可选的字符串参数，指明应用某种Unicode标准形式。</p><p>在ES6中，新增了3个新方法。每个方法都接收2个参数，需要检测的子字符串，以及开始匹配的索引位置。</p><p><strong>模板字符串</strong><br>字符串是JavaScript中基本类型之一，应该算是除了对象之外是使用最为频繁的类型吧，字符串中包含了例如substr，replace，indexOf,slice等等诸多方法，ES6引入了模板字符串的特性，用反引号来表示，可以表示多行字符串以及做到文本插值（利用模板占位符）。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; 以前的多行字符串我们这么写：</span><br><span class="line">console.log(&quot;hello world 1\n\</span><br><span class="line">hello cala&quot;);</span><br><span class="line">&#x2F;&#x2F; &quot;hello world</span><br><span class="line">&#x2F;&#x2F; hello cala&quot;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;有了模板字符串之后</span><br><span class="line">console.log(&#96;hello world</span><br><span class="line">string text line 2&#96;);</span><br><span class="line">&#x2F;&#x2F; &quot;hello world</span><br><span class="line">&#x2F;&#x2F; hello cala&quot;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>可以用<code>$&#123;&#125;</code>来表示模板占位符，可以将你已经定义好的变量传进括弧中，例如：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">var name&#x3D;&quot;cala&quot;;</span><br><span class="line">var age&#x3D;22;</span><br><span class="line">console.log(&#96;hello,I&#39;am $&#123;name&#125;,my age is $&#123;age&#125;&#96;)</span><br><span class="line">&#x2F;&#x2F;hello,I&#39;am cala,my age is 22</span><br><span class="line">includes(str, index)：如果在字符串中检测到指定文本，返回true，否则false。</span><br><span class="line"></span><br><span class="line">let t &#x3D; &#39;abcdefg&#39;</span><br><span class="line">if(t.includes(&#39;cde&#39;)) &#123;</span><br><span class="line">  console.log(2)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F;true</span><br></pre></td></tr></table></figure><p>**startsWith(str, index)**：如果在字符串起始部分检测到指定文本，返回true，否则返回false。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">let t &#x3D; &#39;abcdefg&#39;</span><br><span class="line">if(t.startsWith(&#39;ab&#39;)) &#123;</span><br><span class="line">  console.log(2)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F;true</span><br><span class="line">endsWith(str, index)：如果在字符串的结束部分检测到指定文本，返回true，否则返回false。</span><br><span class="line"></span><br><span class="line">let t &#x3D; &#39;abcdefg&#39;</span><br><span class="line">if(t.endsWith(&#39;fg&#39;)) &#123;</span><br><span class="line">  console.log(2)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F;true</span><br></pre></td></tr></table></figure><p>如果你只是需要匹配字符串中是否包含某子字符串，那么推荐使用新增的方法，如果需要找到匹配字符串的位置，使用<code>indexOf()</code>。</p><h1 id="三、函数"><a href="#三、函数" class="headerlink" title="三、函数"></a>三、函数</h1><h3 id="函数的默认参数"><a href="#函数的默认参数" class="headerlink" title="函数的默认参数"></a>函数的默认参数</h3><p>在ES5中，我们给函数传参数，然后在函数体内设置默认值，如下面这种方式。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">function a(num, callback) &#123;</span><br><span class="line">  num &#x3D; num || 6</span><br><span class="line">  callback &#x3D; callback || function (data) &#123;console.log(&#39;ES5: &#39;, data)&#125;</span><br><span class="line">  callback(num * num)</span><br><span class="line">&#125;</span><br><span class="line">a() &#x2F;&#x2F;ES5: 36，不传参输出默认值</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;你还可以这样使用callback</span><br><span class="line">a(10, function(data) &#123;</span><br><span class="line">  console.log(data * 10) &#x2F;&#x2F; 1000， 传参输出新数值</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>在ES6中，我们使用新的默认值写法</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">function a(num &#x3D; 6, callback &#x3D; function (data) &#123;console.log(&#39;ES6: &#39;, data)&#125;) &#123;</span><br><span class="line">  callback(num * num)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">a() &#x2F;&#x2F;ES6: 36， 不传参输出默认值</span><br><span class="line"></span><br><span class="line">a(10, function(data) &#123;</span><br><span class="line">  console.log(data * 10) &#x2F;&#x2F; 1000，传参输出新数值</span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="四、箭头函数（-gt-）"><a href="#四、箭头函数（-gt-）" class="headerlink" title="四、箭头函数（=&gt;）"></a>四、箭头函数（=&gt;）</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">const arr &#x3D; [5, 10]</span><br><span class="line">const s &#x3D; arr.reduce((sum, item) &#x3D;&gt; sum + item)</span><br><span class="line">console.log(s) &#x2F;&#x2F; 15</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>箭头函数中this的使用跟普通函数也不一样，在JavaScript的普通函数中，都会有一个自己的this值，主要分为：<br><strong>普通函数</strong>：</p><ol><li>函数作为全局函数被调用时，this指向全局对象</li><li>函数作为对象中的方法被调用时，this指向该对象</li><li>函数作为构造函数的时候，this指向构造函数new出来的新对象</li><li>还可以通过call，apply，bind改变this的指向</li></ol><p><strong>箭头函数</strong>：</p><ol><li>箭头函数没有this，函数内部的this来自于父级最近的非箭头函数，并且不能改变this的指向。</li><li>箭头函数没有super</li><li>箭头函数没有arguments</li><li>箭头函数没有new.target绑定。</li><li>不能使用new</li><li>没有原型</li><li>不支持重复的命名参数。</li></ol><h3 id="箭头函数的简单理解"><a href="#箭头函数的简单理解" class="headerlink" title="箭头函数的简单理解"></a>箭头函数的简单理解</h3><h3 id="1、箭头函数的左边表示输入的参数，右边表示输出的结果。"><a href="#1、箭头函数的左边表示输入的参数，右边表示输出的结果。" class="headerlink" title="1、箭头函数的左边表示输入的参数，右边表示输出的结果。"></a>1、箭头函数的左边表示输入的参数，右边表示输出的结果。</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">const s &#x3D; a &#x3D;&gt; a</span><br><span class="line">console.log(s(2)) &#x2F;&#x2F; 2</span><br></pre></td></tr></table></figure><h3 id="2、在箭头函数中，this属于词法作用域，直接由上下文确定，对于普通函数中指向不定的this，箭头函数中处理this无疑更加简单，如下："><a href="#2、在箭头函数中，this属于词法作用域，直接由上下文确定，对于普通函数中指向不定的this，箭头函数中处理this无疑更加简单，如下：" class="headerlink" title="2、在箭头函数中，this属于词法作用域，直接由上下文确定，对于普通函数中指向不定的this，箭头函数中处理this无疑更加简单，如下："></a>2、在箭头函数中，this属于词法作用域，直接由上下文确定，对于普通函数中指向不定的this，箭头函数中处理this无疑更加简单，如下：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;ES5普通函数</span><br><span class="line">function Man()&#123;</span><br><span class="line">  this.age&#x3D;22;</span><br><span class="line">  return function()&#123;</span><br><span class="line">    this.age+1;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">var cala&#x3D;new Man();</span><br><span class="line">console.log(cala())&#x2F;&#x2F;undefined</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;ES6箭头函数</span><br><span class="line">function Man()&#123;</span><br><span class="line">  this.age&#x3D;22;</span><br><span class="line">  return () &#x3D;&gt; this.age+1;</span><br><span class="line">&#125;</span><br><span class="line">var cala&#x3D;new Man();</span><br><span class="line">console.log(cala())&#x2F;&#x2F;23</span><br></pre></td></tr></table></figure><h3 id="3、箭头函数中没有arguments-我们可以用rest参数替代-也没有原型，也不能使用new-关键字，例如："><a href="#3、箭头函数中没有arguments-我们可以用rest参数替代-也没有原型，也不能使用new-关键字，例如：" class="headerlink" title="3、箭头函数中没有arguments(我们可以用rest参数替代),也没有原型，也不能使用new 关键字，例如："></a>3、箭头函数中没有arguments(我们可以用rest参数替代),也没有原型，也不能使用new 关键字，例如：</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;没有arguments</span><br><span class="line">var foo&#x3D;(a,b)&#x3D;&gt;&#123;return arguments[0]*arguments[1]&#125;</span><br><span class="line">console.log(foo(3,5))</span><br><span class="line">&#x2F;&#x2F;arguments is not defined</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;没有原型</span><br><span class="line">var Obj &#x3D; () &#x3D;&gt; &#123;&#125;;</span><br><span class="line">console.log(Obj.prototype); </span><br><span class="line">&#x2F;&#x2F; undefined</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;不能使用new 关键字</span><br><span class="line">var Obj &#x3D; () &#x3D;&gt; &#123;&quot;hello world&quot;&#125;;</span><br><span class="line">var o &#x3D; new Obj(); </span><br><span class="line">&#x2F;&#x2F; TypeError: Obj is not a constructor</span><br></pre></td></tr></table></figure><h3 id="4、箭头函数给数组排序"><a href="#4、箭头函数给数组排序" class="headerlink" title="4、箭头函数给数组排序"></a>4、箭头函数给数组排序</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">const arr &#x3D; [10, 50, 30, 40, 20]</span><br><span class="line">const s &#x3D; arr.sort((a, b) &#x3D;&gt; a - b)</span><br><span class="line">console.log(s) &#x2F;&#x2F; [10,20,30,40,50]</span><br></pre></td></tr></table></figure><h3 id="尾调用优化"><a href="#尾调用优化" class="headerlink" title="尾调用优化"></a>尾调用优化</h3><p>尾调用是指在函数return的时候调用一个新的函数，由于尾调用的实现需要存储到内存中，在一个循环体中，如果存在函数的尾调用，你的内存可能爆满或溢出。</p><p>ES6中，引擎会帮你做好尾调用的优化工作，你不需要自己优化，但需要满足下面3个要求：<br>1、函数不是闭包<br>2、尾调用是函数最后一条语句<br>3、尾调用结果作为函数返回</p><p><strong>尾调用实际用途——递归函数优化</strong><br>在ES5时代，我们不推荐使用递归，因为递归会影响性能。<br>但是有了尾调用优化之后，递归函数的性能有了提升。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;新型尾优化写法</span><br><span class="line">&quot;use strict&quot;;  </span><br><span class="line">function a(n, p &#x3D; 1) &#123;</span><br><span class="line">  if(n &lt;&#x3D; 1) &#123;</span><br><span class="line">    return 1 * p</span><br><span class="line">  &#125;</span><br><span class="line">  let s &#x3D; n * p</span><br><span class="line">  return a(n - 1, s)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F;求 1 x 2 x 3的阶乘</span><br><span class="line">let sum &#x3D; a(3)</span><br><span class="line">console.log(sum) &#x2F;&#x2F; 6</span><br></pre></td></tr></table></figure><h1 id="五、ES6对象新增方法"><a href="#五、ES6对象新增方法" class="headerlink" title="五、ES6对象新增方法"></a>五、ES6对象新增方法</h1><p><strong>Object.assign()</strong><br>Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。<br>Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]]，所以它会调用相关 getter 和 setter。因此，它分配属性，而不仅仅是复制或定义新的属性。如果合并源包含getter，这可能使其不适合将新属性合并到原型中。为了将属性定义（包括其可枚举性）复制到原型，应使用<code>Object.getOwnPropertyDescriptor()</code>和<code>Object.defineProperty()</code>。<br>String类型和 Symbol 类型的属性都会被拷贝。<br>合并对象</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var o1 &#x3D; &#123; a: 1 &#125;;</span><br><span class="line">var o2 &#x3D; &#123; b: 2 &#125;;</span><br><span class="line">var o3 &#x3D; &#123; c: 3 &#125;;</span><br><span class="line">var obj &#x3D; Object.assign(o1, o2, o3);</span><br><span class="line">console.log(obj); &#x2F;&#x2F; &#123; a: 1, b: 2, c: 3 &#125;</span><br><span class="line">console.log(o1);  &#x2F;&#x2F; &#123; a: 1, b: 2, c: 3 &#125;, 注意目标对象自身也会改变。</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>合并具有相同属性的对象</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">var o1 &#x3D; &#123; a: 1, b: 1, c: 1 &#125;;</span><br><span class="line">var o2 &#x3D; &#123; b: 2, c: 2 &#125;;</span><br><span class="line">var o3 &#x3D; &#123; c: 3 &#125;;</span><br><span class="line">var obj &#x3D; Object.assign(&#123;&#125;, o1, o2, o3);</span><br><span class="line">console.log(obj); &#x2F;&#x2F; &#123; a: 1, b: 2, c: 3 &#125;</span><br></pre></td></tr></table></figure><h1 id="六、Map和Set"><a href="#六、Map和Set" class="headerlink" title="六、Map和Set"></a>六、Map和Set</h1><p>Map和Set都叫做集合，但是他们也有所不同。Set常被用来检查对象中是否存在某个键名，Map集合常被用来获取已存的信息。<br>Set是有序列表，含有相互独立的非重复值。</p><h3 id="Array和Set对比"><a href="#Array和Set对比" class="headerlink" title="Array和Set对比"></a>Array和Set对比</h3><p>都是一个存储多值的容器，两者可以互相转换，但是在使用场景上有区别。如下:</p><ul><li>Array的indexOf方法比Set的has方法效率低下</li><li>Set不含有重复值（可以利用这个特性实现对一个数组的去重）</li><li>Set通过delete方法删除某个值，而Array只能通过splice。两者的使用方便程度前者更优</li><li>Array的很多新方法map、filter、some、every等是Set没有的（但是通过两者可以互相转换来使用）</li></ul><h3 id="Object和Map对比"><a href="#Object和Map对比" class="headerlink" title="Object和Map对比"></a>Object和Map对比</h3><ul><li>Object是字符串-值，Map是值-值</li><li>Object键为string类型,Map的键是任意类型</li><li>手动计算Object尺寸,Map.size可以获取尺寸</li><li>Map的排序是插入顺序</li><li>Object有原型，所以映射中有一些缺省的键。可以理解为Map=Object.create(null)</li></ul><h3 id="Set操作集合"><a href="#Set操作集合" class="headerlink" title="Set操作集合"></a>Set操作集合</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">let set &#x3D; new Set()</span><br><span class="line">&#x2F;&#x2F; Set转化为数组</span><br><span class="line">let arr &#x3D; Array.from(set)</span><br><span class="line">let arr &#x3D; [...set]</span><br><span class="line">&#x2F;&#x2F; 实例属性（继承自Set）</span><br><span class="line">set.constructor &#x3D;&#x3D;&#x3D; Set </span><br><span class="line">set.size </span><br><span class="line">&#x2F;&#x2F; 操作方法</span><br><span class="line">set.add(1) &#x2F;&#x2F; 添加一个值</span><br><span class="line">set.delete(1) &#x2F;&#x2F;删除一个值</span><br><span class="line">set.has(1) &#x2F;&#x2F;判断是否有这个值（Array中的indexOf）</span><br><span class="line">set.clear() &#x2F;&#x2F;清除所有值</span><br><span class="line">&#x2F;&#x2F; 获取用于遍历的成员方法(Set的遍历顺序就是插入顺序)</span><br><span class="line">set.keys() &#x2F;&#x2F; 返回键名的遍历器</span><br><span class="line">set.values() &#x2F;&#x2F; 返回键值得遍历器</span><br><span class="line">set.entries() &#x2F;&#x2F; 返回键值对的遍历器</span><br><span class="line">set.forEach() &#x2F;&#x2F; 循环遍历每个值(和Array的方法一致)</span><br><span class="line">for (let key of set.keys())&#123;&#125;</span><br><span class="line">for (let val of set.values())&#123;&#125;</span><br><span class="line">for (let entry of set.entries())&#123;&#125;</span><br><span class="line">&#x2F;&#x2F; 使用数组方法来处理set值</span><br><span class="line">set &#x3D; new Set(arr)</span><br><span class="line">set &#x3D; new Set([...set].map((x) &#x3D;&gt; x &#x3D; x * 2))</span><br><span class="line">set &#x3D; new Set([...set].filter((x) &#x3D;&gt; x &gt; 2))</span><br><span class="line">Map的方法集合</span><br><span class="line"></span><br><span class="line">let map &#x3D; new Map()</span><br><span class="line">&#x2F;&#x2F; 实例属性(继承自Map)</span><br><span class="line">map.constructor &#x3D;&#x3D;&#x3D; Map</span><br><span class="line">map.size</span><br><span class="line">&#x2F;&#x2F; 操作方法</span><br><span class="line">map.set(1,2)</span><br><span class="line">map.get(1)</span><br><span class="line">map.delete(1)</span><br><span class="line">map.has(1)</span><br><span class="line">map.clear()</span><br><span class="line">&#x2F;&#x2F; 遍历方法</span><br><span class="line">map.keys()</span><br><span class="line">map.values()</span><br><span class="line">map.entries()</span><br><span class="line">map.forEach()</span><br><span class="line">&#x2F;&#x2F; Map和数组的转换</span><br><span class="line">map &#x3D; new Map([[&#39;key&#39;,&#39;val&#39;],[2,1]]) &#x2F;&#x2F; 要求双成员数组</span><br><span class="line">let arr &#x3D; [...map]</span><br><span class="line">&#x2F;&#x2F; 值得注意的是Map的键是跟内存绑定的</span><br><span class="line">map.set([1], &#39;s&#39;)</span><br><span class="line">map.get([1])</span><br><span class="line">let arr &#x3D; [1]</span><br><span class="line">let arr1 &#x3D; [1]</span><br><span class="line">map.set(arr, &#39;s&#39;)</span><br><span class="line">map.get(arr)</span><br><span class="line">map.set(arr1, &#39;s&#39;)</span><br><span class="line">map.get(arr1)</span><br></pre></td></tr></table></figure><h1 id="七、迭代器（Iterator）"><a href="#七、迭代器（Iterator）" class="headerlink" title="七、迭代器（Iterator）"></a>七、迭代器（Iterator）</h1><h3 id="1-entries-返回迭代器：返回键值对"><a href="#1-entries-返回迭代器：返回键值对" class="headerlink" title="1. entries() 返回迭代器：返回键值对"></a>1. entries() 返回迭代器：返回键值对</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;数组</span><br><span class="line">const arr &#x3D; [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];</span><br><span class="line">for(let v of arr.entries()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; [0, &#39;a&#39;] [1, &#39;b&#39;] [2, &#39;c&#39;]</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;Set</span><br><span class="line">const arr &#x3D; new Set([&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]);</span><br><span class="line">for(let v of arr.entries()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; [&#39;a&#39;, &#39;a&#39;] [&#39;b&#39;, &#39;b&#39;] [&#39;c&#39;, &#39;c&#39;]</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;Map</span><br><span class="line">const arr &#x3D; new Map();</span><br><span class="line">arr.set(&#39;a&#39;, &#39;a&#39;);</span><br><span class="line">arr.set(&#39;b&#39;, &#39;b&#39;);</span><br><span class="line">for(let v of arr.entries()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; [&#39;a&#39;, &#39;a&#39;] [&#39;b&#39;, &#39;b&#39;]</span><br></pre></td></tr></table></figure><h3 id="2-values-返回迭代器：返回键值对的value"><a href="#2-values-返回迭代器：返回键值对的value" class="headerlink" title="2.values() 返回迭代器：返回键值对的value"></a>2.values() 返回迭代器：返回键值对的value</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;数组</span><br><span class="line">const arr &#x3D; [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];</span><br><span class="line">for(let v of arr.values()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F;&#39;a&#39; &#39;b&#39; &#39;c&#39;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;Set</span><br><span class="line">const arr &#x3D; new Set([&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]);</span><br><span class="line">for(let v of arr.values()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; &#39;a&#39; &#39;b&#39; &#39;c&#39;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;Map</span><br><span class="line">const arr &#x3D; new Map();</span><br><span class="line">arr.set(&#39;a&#39;, &#39;a&#39;);</span><br><span class="line">arr.set(&#39;b&#39;, &#39;b&#39;);</span><br><span class="line">for(let v of arr.values()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; &#39;a&#39; &#39;b&#39;</span><br></pre></td></tr></table></figure><h3 id="3-keys-返回迭代器：返回键值对的key"><a href="#3-keys-返回迭代器：返回键值对的key" class="headerlink" title="3.keys() 返回迭代器：返回键值对的key"></a>3.keys() 返回迭代器：返回键值对的key</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F;数组</span><br><span class="line">const arr &#x3D; [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];</span><br><span class="line">for(let v of arr.keys()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; 0 1 2</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;Set</span><br><span class="line">const arr &#x3D; new Set([&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]);</span><br><span class="line">for(let v of arr.keys()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; &#39;a&#39; &#39;b&#39; &#39;c&#39;</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F;Map</span><br><span class="line">const arr &#x3D; new Map();</span><br><span class="line">arr.set(&#39;a&#39;, &#39;a&#39;);</span><br><span class="line">arr.set(&#39;b&#39;, &#39;b&#39;);</span><br><span class="line">for(let v of arr.keys()) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; &#39;a&#39; &#39;b&#39;</span><br></pre></td></tr></table></figure><p>虽然上面列举了3种内建的迭代器方法，但是不同集合的类型还有自己默认的迭代器，在for of中，数组和Set的默认迭代器是<code>values()</code>，Map的默认迭代器是<code>entries()</code>。</p><p><strong>for of循环解构</strong></p><p>对象本身不支持迭代，但是我们可以自己添加一个生成器，返回一个key，value的迭代器，然后使用for of循环解构key和value。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">const obj &#x3D; &#123;</span><br><span class="line">  a: 1,</span><br><span class="line">  b: 2,</span><br><span class="line">  *[Symbol.iterator]() &#123;</span><br><span class="line">    for(let  in obj) &#123;</span><br><span class="line">      yield [, obj[]]</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">for(let [key, value] of obj) &#123;</span><br><span class="line">  console.log(key, value)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; &#39;a&#39; 1, &#39;b&#39; 2</span><br></pre></td></tr></table></figure><p><strong>字符串迭代器</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">const str &#x3D; &#39;abc&#39;;</span><br><span class="line">for(let v of str) &#123;</span><br><span class="line">  console.log(v)</span><br><span class="line">&#125;</span><br><span class="line">&#x2F;&#x2F; &#39;a&#39; &#39;b&#39; &#39;c&#39;</span><br></pre></td></tr></table></figure><p>ES6给数组添加了几个新方法：<code>find()</code>、<code>findIndex()</code>、<code>fill()</code>、<code>copyWithin()</code><br>**1.find()**：传入一个回调函数，找到数组中符合当前搜索规则的第一个元素，返回它，并且终止搜索。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">const arr &#x3D; [1, &quot;2&quot;, 3, 3, &quot;2&quot;]</span><br><span class="line">console.log(arr.find(n &#x3D;&gt; typeof n &#x3D;&#x3D;&#x3D; &quot;number&quot;)) &#x2F;&#x2F; 1</span><br></pre></td></tr></table></figure><p>**2.findIndex()**：传入一个回调函数，找到数组中符合当前搜索规则的第一个元素，返回它的下标，终止搜索。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">const arr &#x3D; [1, &quot;2&quot;, 3, 3, &quot;2&quot;]</span><br><span class="line">console.log(arr.findIndex(n &#x3D;&gt; typeof n &#x3D;&#x3D;&#x3D; &quot;number&quot;)) &#x2F;&#x2F; 0</span><br></pre></td></tr></table></figure><p>**3.fill()**：用新元素替换掉数组内的元素，可以指定替换下标范围。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">arr.fill(value, start, end)</span><br></pre></td></tr></table></figure><p>**4.copyWithin()**：选择数组的某个下标，从该位置开始复制数组元素，默认从0开始复制。也可以指定要复制的元素范围。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">arr.copyWithin(target, start, end)</span><br><span class="line"></span><br><span class="line">const arr &#x3D; [1, 2, 3, 4, 5]</span><br><span class="line">console.log(arr.copyWithin(3)) &#x2F;&#x2F; [1,2,3,1,2] 从下标为3的元素开始，复制数组，所以4, 5被替换成1, 2</span><br><span class="line"></span><br><span class="line">const arr1 &#x3D; [1, 2, 3, 4, 5]</span><br><span class="line">console.log(arr1.copyWithin(3, 1)) &#x2F;&#x2F; [1,2,3,2,3] 从下标为3的元素开始，复制数组，指定复制的第一个元素下标为1，所以4, 5被替换成2, 3</span><br><span class="line"></span><br><span class="line">const arr2 &#x3D; [1, 2, 3, 4, 5]</span><br><span class="line">console.log(arr2.copyWithin(3, 1, 2)) &#x2F;&#x2F; [1,2,3,2,5] 从下标为3的元素开始，复制数组，指定复制的第一个元素下标为1，结束位置为2，所以4被替换成2</span><br></pre></td></tr></table></figure><h1 id="八、其他"><a href="#八、其他" class="headerlink" title="八、其他"></a>八、其他</h1><p>ES6中类class、Promise与异步编程、代理（Proxy）和反射（Reflection）API</p><hr><blockquote><p>转载自：<a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000016068235">学习ES6笔记──工作中常用到的ES6语法</a></p><p>原文链接：<a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000016068235">https://segmentfault.com/a/1190000016068235</a></p></blockquote><div class="footer"><div class="copyright"><blockquote><p>博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</p><p>本文永久链接是：<a href="https://www.extingstudio.com/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/">https://www.extingstudio.com/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/</a></p></blockquote></div><div class="donate"><div class="imgs"><img src="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/pay/weipayimg.jpg"> <img src="https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/pay/alipayimg.jpg"></div></div></div></div><div class="article-meta" id="bottom"><div class="new-meta-box"><div class="new-meta-item date" itemprop="dateUpdated" datetime="2020-08-25T15:40:26+08:00"><a class="notlink"><i class="fas fa-edit fa-fw" aria-hidden="true"></i><p>更新于：2020年8月25日</p></a></div><div class="new-meta-item meta-tags"><a class="tag" href="/tags/JavaScript/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>JavaScript</p></a></div><div class="new-meta-item share -mob-share-list"><div class="-mob-share-list share-body"><div class="hoverbox"><a class="share"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/wechat.png"></a><div class="target"><img src=""></div></div><a class="-mob-share-qq" rel="external nofollow noopener noreferrer noopener" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=https://www.extingstudio.com/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/&title=工作中常用到的ES6语法 - 忆星辰&summary="><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qq.png"> </a><a class="-mob-share-qzone" rel="external nofollow noopener noreferrer noopener" target="_blank" href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=https://www.extingstudio.com/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/&title=工作中常用到的ES6语法 - 忆星辰&summary="><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qzone.png"> </a><a class="-mob-share-weibo" rel="external nofollow noopener noreferrer noopener" target="_blank" href="http://service.weibo.com/share/share.php?url=https://www.extingstudio.com/2018/09/11/2018-09-10-ES6_Syntax_Commonly_Used_in_Work/&title=工作中常用到的ES6语法 - 忆星辰&summary="><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/weibo.png"></a></div></div></div></div><div class="prev-next"><a class="prev" href="/2018/09/11/2018-09-14-LeetCode_Practice_001/"><p class="title"><i class="fas fa-chevron-left" aria-hidden="true"></i>LeetCode_001 两数之和</p><p class="content">1. 两数之和给定一个整数数组和一个目标值，找出数组中和为目标值的两个数。你可以假设每个输入只对应一种答案，且同样的元素不能被重复利用。 示例： 123给定 nums &#x3D; [2, 7,...</p></a><a class="next" href="/2018/09/07/2018-09-07-About_Use_of_Laya_Timer/"><p class="title">关于Laya的中Timer的使用方法<i class="fas fa-chevron-right" aria-hidden="true"></i></p><p class="content">Laya中Timer的类1.官方文档 Laya.Timer Package laya.utils 类 public class Timer Inheritance Timer → ...</p></a></div></section></article><article class="post white-box reveal comments shadow"><section class="article typo"><p ct><i class="fas fa-comments"></i> 评论</p><section id="comments"><div id="valine_container" class="valine_thread"><i class="fas fa-cog fa-spin fa-fw fa-2x"></i></div></section></section></article></div><aside class="l_side"><section class="widget toc-wrapper shadow desktop mobile" id="toc-div"><header><i class="fas fa-list fa-fw" aria-hidden="true"></i><span class="name">本文目录</span></header><div class="content"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#const%E5%92%8Clet%E7%9A%84%E5%BC%82%E5%90%8C%E7%82%B9"><span class="toc-text">const和let的异同点</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="toc-text">块级作用域的使用场景</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%97%A0%E6%B3%95%E6%B1%A1%E6%9F%93%E5%A4%96%E9%83%A8%E5%87%BD%E6%95%B0"><span class="toc-text">无法污染外部函数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#symbol"><span class="toc-text">symbol</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ES6%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%96%B0%E5%A2%9E%E7%9A%84%E6%96%B9%E6%B3%95"><span class="toc-text">ES6字符串新增的方法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E7%9A%84%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0"><span class="toc-text">函数的默认参数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E7%AE%80%E5%8D%95%E7%90%86%E8%A7%A3"><span class="toc-text">箭头函数的简单理解</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1%E3%80%81%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E5%B7%A6%E8%BE%B9%E8%A1%A8%E7%A4%BA%E8%BE%93%E5%85%A5%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%8C%E5%8F%B3%E8%BE%B9%E8%A1%A8%E7%A4%BA%E8%BE%93%E5%87%BA%E7%9A%84%E7%BB%93%E6%9E%9C%E3%80%82"><span class="toc-text">1、箭头函数的左边表示输入的参数，右边表示输出的结果。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2%E3%80%81%E5%9C%A8%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E4%B8%AD%EF%BC%8Cthis%E5%B1%9E%E4%BA%8E%E8%AF%8D%E6%B3%95%E4%BD%9C%E7%94%A8%E5%9F%9F%EF%BC%8C%E7%9B%B4%E6%8E%A5%E7%94%B1%E4%B8%8A%E4%B8%8B%E6%96%87%E7%A1%AE%E5%AE%9A%EF%BC%8C%E5%AF%B9%E4%BA%8E%E6%99%AE%E9%80%9A%E5%87%BD%E6%95%B0%E4%B8%AD%E6%8C%87%E5%90%91%E4%B8%8D%E5%AE%9A%E7%9A%84this%EF%BC%8C%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E4%B8%AD%E5%A4%84%E7%90%86this%E6%97%A0%E7%96%91%E6%9B%B4%E5%8A%A0%E7%AE%80%E5%8D%95%EF%BC%8C%E5%A6%82%E4%B8%8B%EF%BC%9A"><span class="toc-text">2、在箭头函数中，this属于词法作用域，直接由上下文确定，对于普通函数中指向不定的this，箭头函数中处理this无疑更加简单，如下：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3%E3%80%81%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E4%B8%AD%E6%B2%A1%E6%9C%89arguments-%E6%88%91%E4%BB%AC%E5%8F%AF%E4%BB%A5%E7%94%A8rest%E5%8F%82%E6%95%B0%E6%9B%BF%E4%BB%A3-%E4%B9%9F%E6%B2%A1%E6%9C%89%E5%8E%9F%E5%9E%8B%EF%BC%8C%E4%B9%9F%E4%B8%8D%E8%83%BD%E4%BD%BF%E7%94%A8new-%E5%85%B3%E9%94%AE%E5%AD%97%EF%BC%8C%E4%BE%8B%E5%A6%82%EF%BC%9A"><span class="toc-text">3、箭头函数中没有arguments(我们可以用rest参数替代),也没有原型，也不能使用new 关键字，例如：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4%E3%80%81%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%BB%99%E6%95%B0%E7%BB%84%E6%8E%92%E5%BA%8F"><span class="toc-text">4、箭头函数给数组排序</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B0%BE%E8%B0%83%E7%94%A8%E4%BC%98%E5%8C%96"><span class="toc-text">尾调用优化</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Array%E5%92%8CSet%E5%AF%B9%E6%AF%94"><span class="toc-text">Array和Set对比</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Object%E5%92%8CMap%E5%AF%B9%E6%AF%94"><span class="toc-text">Object和Map对比</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Set%E6%93%8D%E4%BD%9C%E9%9B%86%E5%90%88"><span class="toc-text">Set操作集合</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-entries-%E8%BF%94%E5%9B%9E%E8%BF%AD%E4%BB%A3%E5%99%A8%EF%BC%9A%E8%BF%94%E5%9B%9E%E9%94%AE%E5%80%BC%E5%AF%B9"><span class="toc-text">1. entries() 返回迭代器：返回键值对</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-values-%E8%BF%94%E5%9B%9E%E8%BF%AD%E4%BB%A3%E5%99%A8%EF%BC%9A%E8%BF%94%E5%9B%9E%E9%94%AE%E5%80%BC%E5%AF%B9%E7%9A%84value"><span class="toc-text">2.values() 返回迭代器：返回键值对的value</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-keys-%E8%BF%94%E5%9B%9E%E8%BF%AD%E4%BB%A3%E5%99%A8%EF%BC%9A%E8%BF%94%E5%9B%9E%E9%94%AE%E5%80%BC%E5%AF%B9%E7%9A%84key"><span class="toc-text">3.keys() 返回迭代器：返回键值对的key</span></a></li></ol></div></section></aside></div><footer class="footer clearfix"><br><br><div class="aplayer-container"><meting-js theme="#1BCDFC" autoplay volume="0.5" loop order="random" fixed="true" list-max-height="320px" server="netease" type="playlist" id="3136952023" list-folded="true"></meting-js></div><br><div class="social-wrapper"><a href="/atom.xml" class="social fas fa-rss flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a> <a href="mailto:jaxsonwang@foxmail.com" class="social fas fa-envelope flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a> <a href="https://github.com/BillScott1024/" class="social fab fa-github flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a> <a href="https://music.163.com/#/user/home?id=63035382" class="social fas fa-headphones-alt flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a></div><div><p>博客内容遵循 <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</a></p></div><div><p><span id="lc-sv">本站总访问量为 <span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次</span> <span id="lc-uv">访客数为 <span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 人</span></p></div>本站使用 <a href="https://github.com/volantis-x/hexo-theme-volantis/tree/3.0.0" target="_blank" class="codename">Volantis</a> 作为主题，总访问量为 <span id="busuanzi_value_site_pv"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次<div class="copyright"><p><a href="/">Copyright © 2017-2020 XXX</a></p></div><div><div style="width:300px;margin:0 auto;padding:20px 0"><a style="display:inline-block;text-decoration:none;height:20px;line-height:20px"><img src="/images/beian.png" style="float:left"><p style="float:left;height:20px;line-height:20px;margin:0;color:#939393">鄂公网安备 42011102002596号</p></a></div></div><div><p><img src="https://img.shields.io/badge/Powered-Hexo-blue" style="float:center"> <a target="_blank" rel="noopener" href="https://github.com/BillScott1024/billscott1024.github.io"><img src="https://img.shields.io/badge/Hosted-GitHub-brightgreen" style="float:center"> </a><a target="_blank" rel="noopener" href="https://www.aliyun.com/"><img src="https://img.shields.io/badge/DNS-%E9%98%BF%E9%87%8C%E4%BA%91-orange" style="float:center"> </a><a target="_blank" rel="noopener" href="https://www.jsdelivr.com/"><img src="https://img.shields.io/badge/CDN-JsDelivr-blueviolet" style="float:center"> </a><a target="_blank" rel="noopener" href="https://volantis.js.org/"><img src="https://img.shields.io/badge/Theme-Volantis-blue" style="float:center"> </a><a target="_blank" rel="noopener" href="https://volantis.js.org/"><img src="https://img.shields.io/badge/Theme-Volantis-blue" style="float:center"></a></p></div></footer><a class="s-top fas fa-arrow-up fa-fw" href="javascript:void(0)"></a></div></div><div><script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script><script src="https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js"></script><script type="text/javascript">$(function(){var o=["https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-001.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-002.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-003.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-004.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-005.png","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-006.png","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-007.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-008.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-009.png","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-010.png","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-011.png","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-012.jpg","https://es-blogimg.oss-cn-hangzhou.aliyuncs.com/img/background/cover-013.png"];!function(o){for(var g=o.length;g--;){var c=Math.floor(Math.random()*g),s=o[c];o[c]=o[g],o[g]=s}}(o),$(".cover-backstretch").backstretch(o,{duration:"10000",fade:"1500"})})</script><script>var SEARCH_SERVICE="hexo",ROOT="/";ROOT.endsWith("/")||(ROOT+="/")</script><script defer src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script><script>window.lazyLoadOptions={elements_selector:".lazyload",threshold:0},window.addEventListener("LazyLoad::Initialized",function(n){window.lazyLoadInstance=n.detail.instance},!1),document.addEventListener("DOMContentLoaded",function(){lazyLoadInstance.update()}),document.addEventListener("pjax:complete",function(){lazyLoadInstance.update()})</script><script>window.FPConfig={delay:0,ignoreKeywords:[],maxRPS:5,hoverDelay:25}</script><script defer src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script><script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script><script>function pjax_fancybox(){$(".md").find("img").not(".inline").not("a img").each(function(){var t=document.createElement("a");$(t).attr("class","fancybox"),$(t).attr("pjax-fancybox",""),$(t).attr("href",$(this).attr("src")),$(this).attr("data-original")&&$(t).attr("href",$(this).attr("data-original")),$(t).attr("data-fancybox","images");var a="";$(this).attr("alt")&&($(t).attr("data-caption",$(this).attr("alt")),a=$(this).attr("alt"));var e=document.createElement("div");$(e).addClass("fancybox"),$(this).wrap(e);var r=document.createElement("span");$(r).addClass("image-caption"),$(r).text(a),$(this).after(r);var i=document.createElement("div");$(i).addClass("bg"),$(this).attr("bg")&&$(i).css("background",$(this).attr("bg")),$(this).wrap(i),$(this).wrap(t)}),$(".article-entry").find("img").fancybox({selector:'[data-fancybox="images"]',hash:!1,loop:!1,closeClick:!0,helpers:{overlay:{closeClick:!0}},buttons:["zoom","close"]})}$(function(){pjax_fancybox()})</script><script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script><script>var clipboard = new ClipboardJS('.btn-copy', {
        target: function (trigger) {
            return trigger.nextElementSibling
        }
    });
    function wait(callback, seconds) {
        var timelag = null;
        timelag = window.setTimeout(callback, seconds)
    }
    function pjax_initCopyCode() {
		if($(".highlight .code pre").length+$(".article pre code").length==0)return;
        var copyHtml = '';
        copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
        copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
        copyHtml += '</button>';
        $(".highlight .code pre").before(copyHtml);
        $(".article pre code").before(copyHtml);
        clipboard.off('success').on('success', function (e) {
            let $btn = $(e.trigger);
            $btn.addClass('copied');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-check-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPIED';
            wait(function () {
                $icon.removeClass('fa-check-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        });
        clipboard.off('error').on('error', function (e) {
            e.clearSelection();
            let $btn = $(e.trigger);
            $btn.addClass('copy-failed');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-times-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPY FAILED';
            wait(function () {
                $icon.removeClass('fa-times-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        })
    }
    $(function () {
        pjax_initCopyCode()
    });</script><script src="https://cdn.jsdelivr.net/npm/scrollreveal@4.0.6/dist/scrollreveal.min.js"></script><script type="text/javascript">function pjax_scrollrebeal(){ScrollReveal().reveal(".l_main .reveal",{distance:"32px",duration:"800",interval:"20",scale:"1",easing:"ease-out"})}$(function(){pjax_scrollrebeal()})</script><script>let APlayerController = new Object();
  APlayerController.id = '3136952023';  // 设定全局音乐播放ID
  APlayerController.volume = '0.5';</script><script src="https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/meting@2.0/dist/Meting.min.js"></script><script src="/js/valine.js"></script><script>var GUEST_INFO = ['nick', 'mail', 'link'];
  var meta = 'nick,mail,link'.split(',').filter(function (item) {
    return GUEST_INFO.indexOf(item) > -1
  });
  var REQUIRED_FIELDS = ['nick', 'mail', 'link'];
  var requiredFields = 'nick,mail'.split(',').filter(function (item) {
    return REQUIRED_FIELDS.indexOf(item) > -1
  });

  function emoji(path, idx, ext) {
    return path + "/" + path + "-" + idx + "." + ext;
  }

  var emojiMaps = {};
  for (var i = 1; i <= 54; i++) {
    emojiMaps['tieba-' + i] = emoji('tieba', i, 'png');
  }
  for (var i = 1; i <= 101; i++) {
    emojiMaps['qq-' + i] = emoji('qq', i, 'gif');
  }
  for (var i = 1; i <= 116; i++) {
    emojiMaps['aru-' + i] = emoji('aru', i, 'gif');
  }
  for (var i = 1; i <= 125; i++) {
    emojiMaps['twemoji-' + i] = emoji('twemoji', i, 'png');
  }
  for (var i = 1; i <= 4; i++) {
    emojiMaps['weibo-' + i] = emoji('weibo', i, 'png');
  }

  function pjax_valine() {
    if(!document.querySelectorAll("#valine_container")[0])return;
    let pageUrl = $.trim($('#pjax-comment-path').text()) === "none" ? 
      decodeURI(window.location.pathname) : $.trim($('#pjax-comment-path').text());
    let pagePlaceholder = $.trim($('#pjax-comment-placeholder').text()) === "none" ?
      "粘贴图片到此处可以自动上传，请填写邮箱以收到及时回复哦~" : $.trim($('#pjax-comment-placeholder').text());

    let ALLPATH = '';
    if(ALLPATH != '') pageUrl = ALLPATH;

    var valine = new Valine();
    valine.init({
      el: '#valine_container',
      meta: meta,
      placeholder: pagePlaceholder,
      path: pageUrl,
      appId: "p9EoaNrAJAtz2IlbAp0sRau5-gzGzoHsz",
      appKey: "u1u31xRPwMb606uCUaaCaV3A",
      pageSize: '10',
      avatar: 'robohash',
      lang: 'zh-cn',
      visitor: 'true',
      highlight: 'true',
      mathJax: 'false',
      enableQQ: 'true',
      requiredFields: requiredFields,
      emojiCDN: 'https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/valine/',
      emojiMaps: emojiMaps
    })
  }

  $(function () {
    pjax_valine();
  });</script><script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5/lib/darkmode-js.min.js" aysc></script><script type="text/javascript">function getClientHeight(){var e=0;if(document.body.clientHeight&&document.documentElement.clientHeight)e=document.body.clientHeight<document.documentElement.clientHeight?document.body.clientHeight:document.documentElement.clientHeight;else e=document.body.clientHeight>document.documentElement.clientHeight?document.body.clientHeight:document.documentElement.clientHeight;return e}function supportCss3(e){var t,o=["webkit","Moz","ms","o"],n=[],d=document.documentElement.style,i=function(e){return e.replace(/-(\w)/g,function(e,t){return t.toUpperCase()})};for(t in o)n.push(i(o[t]+"-"+e));for(t in n.push(i(e)),n)if(n[t]in d)return!0;return!1}var options={bottom:"32px",right:"unset",left:"16px",time:"0s",mixColor:"#f4f4f4",backgroundColor:"#f4f4f4",buttonColorDark:"#bbb",buttonColorLight:"#444",saveInCookies:!0,label:"🌓",autoMatchOsTheme:!0};function pjax_darkmodejs(){if(supportCss3("mix-blend-mode"))var e=setInterval(function(){if("undefined"!=typeof jQuery){clearInterval(e);var t=getClientHeight();$(window).scroll(function(){var e=$(document).scrollTop();t<e?($(".darkmode-layer").css("mix-blend-mode","normal"),$(".darkmode-layer").css("background-color","#222")):($(".darkmode-layer").css("mix-blend-mode","difference"),$(".darkmode-layer").css("background-color",""))})}},100)}supportCss3("mix-blend-mode")&&(window.darkmode=new Darkmode(options),window.darkmode.showWidget(),pjax_darkmodejs())</script><script defer src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-busuanzi@2.3/js/busuanzi.pure.mini.js" data-pjax></script><script src="/js/app.js"></script><script src="/js/search.js"></script><script src="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.js"></script><script type="text/javascript">$(function(){Waves.attach(".flat-btn",["waves-button"]),Waves.attach(".float-btn",["waves-button","waves-float"]),Waves.attach(".float-btn-light",["waves-button","waves-float","waves-light"]),Waves.attach(".flat-box",["waves-block"]),Waves.attach(".float-box",["waves-block","waves-float"]),Waves.attach(".waves-image"),Waves.init()})</script><script defer>const LCCounter = {
    app_id: 'OcH33On9kof4QnMnSaAOmDhj-MdYXbMMI',
    app_key: 'V50w1D4JtUK9s3VxbnTtg5XJ',
    custom_api_server: '',

    // 查询存储的记录
    getRecord(Counter, url, title) {
      return new Promise(function (resolve, reject) {
        Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({url})))
          .then(resp => resp.json())
          .then(({results, code, error}) => {
            if (code === 401) {
              throw error;
            }
            if (results && results.length > 0) {
              var record = results[0];
              resolve(record);
            } else {
              Counter('post', '/classes/Counter', {url, title: title, times: 0})
                .then(resp => resp.json())
                .then((record, error) => {
                  if (error) {
                    throw error;
                  }
                  resolve(record);
                }).catch(error => {
                console.error('Failed to create', error);
                reject(error);
              });
            }
          }).catch((error) => {
          console.error('LeanCloud Counter Error:', error);
          reject(error);
        });
      })
    },

    // 发起自增请求
    increment(Counter, incrArr) {
      return new Promise(function (resolve, reject) {
        Counter('post', '/batch', {
          "requests": incrArr
        }).then((res) => {
          res = res.json();
          if (res.error) {
            throw res.error;
          }
          resolve(res);
        }).catch((error) => {
          console.error('Failed to save visitor count', error);
          reject(error);
        });
      });
    },

    // 构建自增请求体
    buildIncrement(objectId) {
      return {
        "method": "PUT",
        "path": `/1.1/classes/Counter/${ objectId }`,
        "body": {
          "times": {
            '__op': 'Increment',
            'amount': 1
          }
        }
      }
    },

    // 校验是否为有效的 UV
    validUV() {
      var key = 'LeanCloudUVTimestamp';
      var flag = localStorage.getItem(key);
      if (flag) {
        // 距离标记小于 24 小时则不计为 UV
        if (new Date().getTime() - parseInt(flag) <= 86400000) {
          return false;
        }
      }
      localStorage.setItem(key, new Date().getTime().toString());
      return true;
    },

    addCount(Counter) {
      var enableIncr = '' === 'true' && window.location.hostname !== 'localhost';
      enableIncr = true;
      var getterArr = [];
      var incrArr = [];
      // 请求 PV 并自增
      var pvCtn = document.querySelector('#lc-sv');
      if (pvCtn || enableIncr) {
        var pvGetter = this.getRecord(Counter, 'https://www.extingstudio.com' + '/#lc-sv', 'Visits').then((record) => {
          incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-sv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + 1;
              if (pvCtn) {
                pvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(pvGetter);
      }

      // 请求 UV 并自增
      var uvCtn = document.querySelector('#lc-uv');
      if (uvCtn || enableIncr) {
        var uvGetter = this.getRecord(Counter, 'https://www.extingstudio.com' + '/#lc-uv', 'Visitors').then((record) => {
          var vuv = this.validUV();
          vuv && incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-uv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + (vuv ? 1 : 0);
              if (uvCtn) {
                uvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(uvGetter);
      }

      // 请求文章的浏览数，如果是当前页面就自增
      var allPV = document.querySelectorAll('#lc-pv');
      if (allPV.length > 0 || enableIncr) {
        for (i = 0; i < allPV.length; i++) {
          let pv = allPV[i];
          let title = pv.getAttribute('data-title');
          var url = 'https://www.extingstudio.com' + pv.getAttribute('data-path');
          if (url) {
            var viewGetter = this.getRecord(Counter, url, title).then((record) => {
              // 是当前页面就自增
              if (pv.getAttribute('data-path') == window.location.pathname) {
                incrArr.push(this.buildIncrement(record.objectId));
              }
              if (pv) {
                var ele = pv.querySelector('#lc-pv #number');
                if (ele) {
                  if (pv.getAttribute('data-path') == window.location.pathname) {
                    ele.innerText = (record.times || 0) + 1;
                  } else {
                    ele.innerText = record.times || 0;
                  }
                  pv.style.display = 'inline';
                }
              }
            });
            getterArr.push(viewGetter);
          }
        }
      }

      // 如果启动计数自增，批量发起自增请求
      if (enableIncr) {
        Promise.all(getterArr).then(() => {
          incrArr.length > 0 && this.increment(Counter, incrArr);
        })
      }

    },


    fetchData(api_server) {
      var Counter = (method, url, data) => {
        return fetch(`${ api_server }/1.1${ url }`, {
          method,
          headers: {
            'X-LC-Id': this.app_id,
            'X-LC-Key': this.app_key,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      this.addCount(Counter);
    },

    refreshCounter() {
      var api_server = this.app_id.slice(-9) !== '-MdYXbMMI' ? this.custom_api_server : `https://${ this.app_id.slice(0, 8).toLowerCase() }.api.lncldglobal.com`;
      if (api_server) {
        this.fetchData(api_server);
      } else {
        fetch('https://app-router.leancloud.cn/2/route?appId=' + this.app_id)
          .then(resp => resp.json())
          .then(({api_server}) => {
            this.fetchData('https://' + api_server);
          });
      }
    }

  };

  LCCounter.refreshCounter();

  document.addEventListener('pjax:complete', function () {
    LCCounter.refreshCounter();
  });</script><!-- more --><script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script><div class="pjax-animate"><script src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js"></script><div id="loading-bar-wrapper"><script>NProgress.configure({parent:"#loading-bar-wrapper",trickleSpeed:100})</script></div><script>window.ShowLoading=function(){NProgress.start()},window.HideLoading=function(){NProgress.done()}</script></div><script>var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',
        selectors: [
          "title",
          "#pjax-container",
          "#pjax-header-nav-list"
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000
      });
    });

    document.addEventListener('pjax:send', function (e) {
      window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = ["/shuoshuo/"];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      window.subData = null; // 移除标题（用于一二级导航栏切换处）
      $.fancybox.close();    // 关闭弹窗
      $('.l_header .switcher .s-search').removeClass('active'); // 关闭移动端激活的搜索框
      $('.l_header').removeClass('z_search-open'); // 关闭移动端激活的搜索框
      $('.wrapper').removeClass('sub'); // 跳转页面时关闭二级导航

      // 解绑事件 避免重复监听
      $('.s-top').unbind('click');
      $('.menu a').unbind('click');
      $(window).unbind('resize');
      $(window).unbind('scroll');
      $(document).unbind('scroll');
      $(document).unbind('click');
      $('body').unbind('click');
      window.ShowLoading();
    });

    document.addEventListener('pjax:complete', function () {
      // 关于百度统计对 SPA 页面的处理：
      // 方案一：百度统计>管理>单页应用设置中，打开开启按钮即可对SPA进行统计。 https://tongji.baidu.com/web/help/article?id=324
      // 方案二：取消注释下列代码。 https://tongji.baidu.com/web/help/article?id=235
      // 
      // _hmt.push(['_trackPageview', document.location.pathname]);
      // 

      // 关于谷歌统计对 SPA 页面的处理：
      // 当应用以动态方式加载内容并更新地址栏中的网址时，也应该更新通过 gtag.js 存储的网页网址。
      // https://developers.google.cn/analytics/devguides/collection/gtagjs/single-page-applications?hl=zh-cn
      
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('config', 'UA-124641144-1', {'page_path': document.location.pathname});
      

      $('.nav-main').find('.list-v').not('.menu-phone').removeAttr("style",""); // 移除小尾巴的移除
      $('.menu-phone.list-v').removeAttr("style",""); // 移除小尾巴的移除
      $('script[data-pjax], .pjax-reload script').each(function () {
        $(this).parent().append($(this).remove());
      });
      try{
        pjax_fancybox();
        
          
          if ('.cover-backstretch') {
            $('.cover-backstretch').backstretch("resize");
            if($('.cover-wrapper').is(':hidden')){
              $('.cover-backstretch').backstretch("pause");
            }else{
              $('.cover-backstretch').backstretch("next");
            }
          } else {
            $.backstretch("resize");
            if($('.cover-wrapper').is(':hidden')){
              $.backstretch("pause");
            }else{
              $.backstretch("next");
            }
          }
        
        
        
          pjax_scrollrebeal();
        
        
          pjax_initCopyCode();
        
        
          pjax_valine();
        
        
        
        
        
          pjax_darkmodejs();
        
      } catch (e) {
        console.log(e);
      }
      window.HideLoading();
    });

    document.addEventListener('pjax:error', function (e) {
      window.HideLoading();
      window.location.href = e.triggerElement.href;
    });</script></div><script>(function(w,d, s, id) {w.webpushr=w.webpushr||function(){(w.webpushr.q=w.webpushr.q||[]).push(arguments)};var js, fjs = d.getElementsByTagName(s)[0];js = d.createElement(s); js.id = id;js.src = 'https://cdn.webpushr.com/app.min.js';fjs.parentNode.appendChild(js);}(window,document, 'script', 'webpushr-jssdk'));webpushr('init','BNKbIvI_iJuSO3IFPx6D_gSjEve8q7iuxD8qMSMRfWMq0JSx0xRSadjd-x6TX8XI537fa3c7fGsgeic-ejD6l-o');</script></body></html>